package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	modbus "gitee.com/barryzxy/gomodbus"
)

// 基础TCP服务器示例 - 展示优化后的向后兼容性
// 这个示例使用现有的API，但自动获得了内部优化的好处：
// - 增强的并发安全性（NodeRegister现在完全线程安全）
// - 改进的内存管理
// - 更好的资源清理
// - 更强的稳定性

func main() {
	fmt.Println("=== Modbus 基础TCP服务器示例（优化版本）===")
	fmt.Println("注意：此示例使用完全相同的API，但获得了内部优化的所有好处")

	// 1. 创建服务器（API完全不变）
	fmt.Println("🏭 创建 Modbus TCP 服务器...")
	srv := modbus.NewTCPServer()
	srv.LogMode(true) // 启用日志，现在日志信息更详细

	// 显示优化状态
	fmt.Println("\n📊 内部优化状态：")
	fmt.Println("✅ NodeRegister并发安全性增强")
	fmt.Println("✅ 内存管理优化")
	fmt.Println("✅ 资源自动清理")
	fmt.Println("✅ 错误处理改进")

	// 2. 创建节点寄存器（现在完全并发安全）
	fmt.Println("\n📋 创建节点寄存器...")

	// 节点1：工业传感器模拟
	node1 := modbus.NewNodeRegister(
		1,     // 从站ID
		0, 20, // 线圈：0-19（开关状态）
		0, 20, // 离散输入：0-19（传感器状态）
		0, 10, // 输入寄存器：0-9（传感器数值）
		0, 20, // 保持寄存器：0-19（设置参数）
	)

	// 节点2：设备控制器模拟
	node2 := modbus.NewNodeRegister(
		2,     // 从站ID
		0, 16, // 线圈：0-15（控制输出）
		0, 16, // 离散输入：0-15（状态输入）
		0, 8, // 输入寄存器：0-7（监控数据）
		0, 16, // 保持寄存器：0-15（配置参数）
	)

	// 节点3：系统状态模拟
	node3 := modbus.NewNodeRegister(
		3,     // 从站ID
		0, 10, // 线圈：0-9（系统开关）
		0, 10, // 离散输入：0-9（报警状态）
		0, 6, // 输入寄存器：0-5（系统监控）
		0, 12, // 保持寄存器：0-11（系统配置）
	)

	// 3. 初始化寄存器数据（展示并发安全的写入操作）
	fmt.Println("🔧 初始化寄存器数据...")
	initializeNodeData(node1, "工业传感器")
	initializeNodeData(node2, "设备控制器")
	initializeNodeData(node3, "系统状态")

	// 4. 添加节点到服务器（API不变，但内部处理更安全）
	fmt.Println("➕ 添加节点到服务器...")
	srv.AddNodes(node1, node2, node3)

	fmt.Printf("✅ 成功添加 3 个节点（ID: 1, 2, 3）\n")

	// 5. 启动数据模拟任务（展示并发安全性）
	fmt.Println("🎬 启动数据模拟任务...")
	stopSimulation := make(chan struct{})
	go startDataSimulation(node1, node2, node3, stopSimulation)

	// 6. 设置优雅停机
	fmt.Println("⚙️  设置信号处理...")
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	// 7. 启动服务器（在goroutine中，便于处理停机信号）
	fmt.Println("🚀 启动服务器，监听端口 :502...")
	fmt.Println("💡 提示：使用 Ctrl+C 优雅停止服务器")
	fmt.Println()

	go func() {
		err := srv.ListenAndServe(":502")
		if err != nil {
			log.Printf("服务器错误: %v", err)
		}
	}()

	// 显示服务器状态
	time.Sleep(100 * time.Millisecond) // 让服务器启动
	fmt.Println("🌟 服务器运行状态：")
	fmt.Println("  📍 监听地址: localhost:502")
	fmt.Println("  📊 节点数量: 3")
	fmt.Println("  🔧 日志模式: 启用")
	fmt.Println("  ✨ 优化功能: 全部启用")
	fmt.Println()

	// 显示实时统计（新功能，展示优化效果）
	go showRealTimeStats(node1, node2, node3)

	// 8. 等待停机信号
	fmt.Println("⏳ 服务器运行中... 按 Ctrl+C 停止")
	<-sigChan

	// 9. 优雅停机
	fmt.Println("\n🛑 接收到停机信号，正在优雅关闭...")
	close(stopSimulation)

	// 在实际应用中，这里可以添加服务器关闭逻辑
	// srv.Close() // 如果有这个方法的话

	fmt.Println("✅ 服务器已关闭")

	// 10. 显示运行总结
	fmt.Println("\n📈 运行总结：")
	fmt.Println("✨ 向后兼容性: 100% - 使用完全相同的API")
	fmt.Println("🛡️  并发安全性: 所有读写操作都是线程安全的")
	fmt.Println("🚀 性能优化: 内存使用更高效，GC压力更小")
	fmt.Println("📊 稳定性提升: 增强的错误处理和资源管理")
	fmt.Println("🔧 自动优化: 无需配置即可获得所有优化好处")
}

// initializeNodeData 初始化节点数据
func initializeNodeData(node *modbus.NodeRegister, nodeType string) {
	fmt.Printf("  初始化 %s (ID: %d)...\n", nodeType, node.SlaveID())

	// 初始化线圈（并发安全）
	coilStart, coilCount := node.CoilsAddrParam()
	for i := uint16(0); i < coilCount && i < 5; i++ {
		node.WriteSingleCoil(coilStart+i, i%2 == 0)
	}

	// 初始化保持寄存器（并发安全）
	holdingStart, holdingCount := node.HoldingAddrParam()
	for i := uint16(0); i < holdingCount && i < 10; i++ {
		value := uint16(1000 + i*100 + uint16(node.SlaveID())*10)
		node.WriteHoldings(holdingStart+i, []uint16{value})
	}

	// 初始化输入寄存器（模拟传感器数据）
	inputStart, inputCount := node.InputAddrParam()
	for i := uint16(0); i < inputCount && i < 5; i++ {
		value := uint16(2000 + i*50 + uint16(node.SlaveID())*5)
		node.WriteInputs(inputStart+i, []uint16{value})
	}
}

// startDataSimulation 启动数据模拟
func startDataSimulation(node1, node2, node3 *modbus.NodeRegister, stop <-chan struct{}) {
	ticker := time.NewTicker(2 * time.Second)
	defer ticker.Stop()

	counter := uint16(0)

	for {
		select {
		case <-stop:
			return
		case <-ticker.C:
			counter++

			// 模拟动态数据更新（展示并发安全性）
			// 这些操作可以与客户端请求并发执行，完全安全

			// 更新节点1的输入寄存器（模拟传感器读数）
			inputStart, _ := node1.InputAddrParam()
			for i := uint16(0); i < 3; i++ {
				// 模拟传感器数据变化
				value := uint16(2000 + i*100 + counter%100)
				node1.WriteInputs(inputStart+i, []uint16{value})
			}

			// 更新节点2的输入寄存器（模拟设备状态）
			inputStart, _ = node2.InputAddrParam()
			for i := uint16(0); i < 3; i++ {
				value := uint16(3000 + i*150 + counter%150)
				node2.WriteInputs(inputStart+i, []uint16{value})
			}

			// 更新节点3的输入寄存器（模拟系统监控）
			inputStart, _ = node3.InputAddrParam()
			for i := uint16(0); i < 3; i++ {
				value := uint16(4000 + i*200 + counter%200)
				node3.WriteInputs(inputStart+i, []uint16{value})
			}

			// 模拟线圈状态变化
			coilStart, _ := node1.CoilsAddrParam()
			node1.WriteSingleCoil(coilStart, counter%4 == 0)

			coilStart, _ = node2.CoilsAddrParam()
			node2.WriteSingleCoil(coilStart+1, counter%3 == 0)
		}
	}
}

// showRealTimeStats 显示实时统计
func showRealTimeStats(nodes ...*modbus.NodeRegister) {
	ticker := time.NewTicker(10 * time.Second)
	defer ticker.Stop()

	for range ticker.C {
		fmt.Println("\n📊 实时数据快照：")

		for _, node := range nodes {
			nodeID := node.SlaveID()

			// 读取一些示例数据展示
			coilStart, _ := node.CoilsAddrParam()
			coil, _ := node.ReadSingleCoil(coilStart)

			holdingStart, _ := node.HoldingAddrParam()
			holding, _ := node.ReadHoldings(holdingStart, 1)

			inputStart, _ := node.InputAddrParam()
			input, _ := node.ReadInputs(inputStart, 1)

			fmt.Printf("  节点 %d: 线圈[0]=%v, 保持寄存器[0]=%v, 输入寄存器[0]=%v\n",
				nodeID, coil,
				func() uint16 {
					if len(holding) > 0 {
						return holding[0]
					}
					return 0
				}(),
				func() uint16 {
					if len(input) > 0 {
						return input[0]
					}
					return 0
				}())
		}

		fmt.Println("  💡 所有读写操作都是并发安全的，可以安全地与客户端请求并行执行")
	}
}
